#pragma once


// macros used in the COM part of the code
#define		USES_ERROR_HANDLING\
	HRESULT		__eh_result = S_OK;

#define		REPORT_STATUS\
	return	__eh_result;\

#define		CURRENT_STATUS  (__eh_result)



using namespace System;
using namespace System::Reflection;


namespace Microsoft
{
namespace SqlServer
{
namespace DataMining
{
namespace PluginAlgorithms
{
	private ref class DMEngineException : public System::Exception 
    {
	public:
		DMEngineException( HRESULT hRet )
		{
			TraceCOMError(hRet);
			m_hRet	=	hRet;
		}

		property HRESULT Result
		{
			HRESULT get()
			{
				return m_hRet;
			}
		}

	protected:
		HRESULT		m_hRet;
	};
}	
}
}
}
using namespace Microsoft::SqlServer::DataMining;


HRESULT		DMHRESULTFromServerError( Microsoft::SqlServer::DataMining::PluginAlgorithms::DMEngineException^ dmex);
HRESULT		DMHRESULTFromAlgorithmError( System::Exception^ pex);

#define		DM_TRY									\
	int	__inside_dmtry = 1;							\
	try												\



// Macro for handling an exception
#define DM_HANDLE_EXCEPTION(ex)											\
	if( DMEngineException::typeid->IsInstanceOfType(ex) )				\
	{																	\
		__eh_result = DMHRESULTFromServerError((DMEngineException^)ex);\
	}																	\
	else																\
	{																	\
		__eh_result = DMHRESULTFromAlgorithmError(ex);					\
	}																	\


#define DM_CATCHALL										\
	__if_not_exists(__inside_dmtry)						\
	{													\
		char DM_CATCHALL_Does_not_match_DM_TRY[0];		\
	}													\
	catch(System::Exception^ pex)						\
	{													\
		DM_HANDLE_EXCEPTION(pex);						\
	}													\



#define DM_CATCH_EX(ExceptionDecl)											\
	__if_not_exists(__inside_dmtry)											\
	{																		\
		char DM_CATCH_EX_Does_not_match_DM_TRY[0];							\
	}																		\
	catch(##ExceptionDecl)													\


#define		DM_FINALLY								\
	__if_not_exists(__inside_dmtry)					\
	{												\
		char DM_FINALLY_Does_not_match_DM_TRY[0];	\
	}												\
	finally




// RETURN_ON_FAILURE -- checks a COM call and returns a failure
// THIS SHOULD NEVER BE USED INSIDE A TRY/CATCH BLOCK
#define		RETURN_ON_FAILURE(x)							\
	__if_exists(__inside_dmtry)						\
	{												\
		char RETURN_ON_FAILURE_Cannot_be_used_inside_DM_TRY[0];\
	}												\
	__eh_result	=	x;								\
	if(!SUCCEEDED(__eh_result))						\
	{												\
        TraceCOMError(__eh_result);					\
		return __eh_result;							\
	}



// THROW_ON_FAILURE --  CALLS A SERVER FUNCTION AND THROWS A DMEngineException EXCEPTION
// WHICH WRAPS THE HRESULT. SHOULD ONLY BE CALLED FROM INSIDE TRY/CATCH blocks
#define		THROW_ON_FAILURE(x)\
	if( !SUCCEEDED(__eh_result = (x) ) )\
		throw gcnew PluginAlgorithms::DMEngineException(__eh_result);
